package br.com.pibjp.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;


public abstract class GenericHibernateDAO<T> implements IGenericDAO<T> {
	private static final String PERSISTENCE_UNIT = "CursilhoPU";

	protected EntityManagerSingleton entityManagerSingleton;
	protected EntityManagerFactory factory;
	protected Session session;

	private Class<T> persistentClass;

	public GenericHibernateDAO(Class<T> persistentClass) {
		this.factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
		this.persistentClass = persistentClass;
		this.entityManagerSingleton = EntityManagerSingleton.getInstance();
	}
	
	public void openSession(){
		EntityManager entityManager = entityManagerSingleton.getEntityManager(factory);
		
		if(this.session == null)
			this.session = (Session) entityManager.getDelegate();
	}

	@Override
	public T selectById(int id) {
		EntityManager entityManager = entityManagerSingleton.getEntityManager(factory);
		
		T t = null;
		try {
			t = entityManager.find(persistentClass, id);
		} catch (Exception e) {
			e.getStackTrace();
		}
		return t;
	}

	@Override
	public List<T> selectAll(){
		this.openSession();
		Criteria criteria = session.createCriteria(persistentClass);
		List<T> result = null;
		
		try{
			result = (List<T>) criteria.list();
		} catch (Exception e) {
			e.getStackTrace();
		}
		return result;
	}

	@Override
	public List<T> selectWhere(Criterion ... criterion) {
		Criteria criteria = null;
		List<T> result = null;
		try{
			this.openSession();
			criteria = session.createCriteria(persistentClass);
			for(Criterion c : criterion){
				criteria.add(c);
			}
			
			result = (List<T>) criteria.list();
		} catch (Exception e) {
			e.getStackTrace();
		}
		return result;
	}

	@Override
	public T create(T entity) {
		try{
			EntityManager entityManager = this.entityManagerSingleton.getEntityManager(factory);
			
			entityManager.getTransaction().begin();
			entityManager.persist(entity);
			entityManager.getTransaction().commit();
		} catch (Exception e) {
			e.getStackTrace();
		}
		return entity;
	}

	@Override
	public T update(T entity){
		try { 
			EntityManager entityManager = this.entityManagerSingleton.getEntityManager(factory);
			
			entityManager.getTransaction().begin();
			entityManager.merge(entity);
			entityManager.getTransaction().commit();
		} catch (Exception e) {
			e.getStackTrace();
		}
		return entity;
	}
	
	public void delete(T entity){
		try {
			EntityManager entityManager = this.entityManagerSingleton.getEntityManager(factory);
			entityManager.getTransaction().begin();
			entityManager.merge(entity);
			entityManager.remove(entity);
			entityManager.getTransaction().commit();
		} catch (Exception e) {
			e.getStackTrace();
		}
	}
}
